'''
Created on Jan 25, 2011

@author: Jialai_Zhu
'''
import  os
import  subprocess        
class ChildProcess(object):
    ProcessList=[]
    ProcessListId=0
    def __init__(self,name,args,cwd=None,shell=True,exe=None):
        self._name=name
        self._args=args
        self._shell=shell
        self._cwd=cwd
        self._exe=exe
#        ChildProcess.ProcessListId=self._id=ChildProcess.ProcessListId+1
    def Run(self):
        
        try:
            if self._cwd==None:
                self._cwd=os.getcwd()
            if self._exe==None:
                self._popen=subprocess.Popen(args=self._args,shell=self._shell,cwd=self._cwd)
            else:
                self._popen=subprocess.Popen(args='"%s" %s'%(self._exe,self._args),shell=self._shell,cwd=self._cwd)
#                                         ,stdout = subprocess.PIPE, stderr=subprocess.STDOUT)
#            ChildProcess.ProcessList.append(self)
            print('%s %s'%(self._args,self._popen.pid))
        except Exception,ex:
            print('%s %s'%(self._args,ex))
#        print 'Create Process %s'%(self._name)
    def Kill(self,name=None):
        if name==None or self._name==name:
            if self._popen.poll()!=None:
                ChildProcess.ProcessList.remove(self)
    def Wait(self,timeout):
        # if timeout is not set wait for process to complete
        if not timeout:
            ph_ret = self._popen.wait()
        else:
            import time
            fin_time = time.time() + timeout
            while self._popen.poll() == None and fin_time > time.time():
                time.sleep(1)
        
            # if timeout reached, raise an exception
            if fin_time < time.time():  
                self._popen.kill()
                return True
        return False        
    def RunAndWait(self,timeout=0):
        self.Run()
        return self.Wait(timeout)

    
import os
import getopt, sys
class CommandLine(object):
    def __init__(self,config):
        self.opts, self.args = getopt.getopt(sys.argv[1:], self.short_option(), self.long_option())
        self.config=config
        self.ProcessCommand()
    def ProcessCommand(self):
        for o, a in self.opts:
            self.ProcessCommandOther(o, a)
    def short_option(self):raise
    def long_option(self):return []
    def ProcessCommandOther(self,o, a):raise
class ChildCommandLine(CommandLine):
    def short_option(self):return "c"
    def ProcessCommandOther(self,o, a):
        if o=='-c':
            self.config.child=True  
class PythonProcessInstance(object):
    def __init__(self,pyFile):
        self.pyFile=pyFile
        self.child=False
        self.GetCommandLine()
    def GetCommandLine(self):
        self.command_line=ChildCommandLine(self)
        return  self.command_line
        
    def IsChild(self):
        return self.child
    def CommandChild(self):
        raise
    def Child(self):raise
    def Parent(self):raise
    def LauchChild(self):
        PythonProcess(os.path.basename(self.pyFile),'%s -c %s'%(self.pyFile,self.CommandChild())).Run()
    def Run(self):
        if self.IsChild():
            self.Child()
        else:
            self.Parent()
class PythonProcess(ChildProcess):
    def __init__(self,name,args,cwd=None):
        python="python.exe %s"%(args)
        print python
        ChildProcess.__init__(self, name, python,cwd)
             
def KillAll(name):
    for p in ChildProcess.ProcessList:
        p.Kill(name)
def Wait(name):
    totalTask=len(ChildProcess.ProcessList)
    print( "Total Task %d"%(totalTask))
    KillAll(name)
    leftTask=len(ChildProcess.ProcessList)
    print "LeftTask Task",leftTask,totalTask*30/100
    if leftTask>totalTask*30/100:
        print 'Wait for uncompleted task'
        import time 
        time.sleep(30)
        KillAll(name)
    leftTask=len(ChildProcess.ProcessList)
    print 'Uncompleted task',leftTask
 
import unittest

class ChildProcessTestCase(unittest.TestCase):
    def testCreate(self):
        ChildProcess('explorer','cmd.exe').Run() 
#        KillAll('explorer')
